package org.infodavid.common.model.impl;

import java.util.Properties;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.pool.BasePoolableObjectFactory;
import org.apache.commons.pool.PoolableObjectFactory;
import org.apache.commons.pool.impl.GenericObjectPool;
import org.apache.commons.pool.impl.GenericObjectPool.Config;
import org.infodavid.common.pool.AbstractPooledFactory;
import org.infodavid.common.pool.impl.ConfigLoaderHelper;
import org.infodavid.common.reflect.InstantiationHelper;

/**
 * The Class PropertyChangeEventFactory.
 */
public class PropertyChangeEventFactory extends AbstractPooledFactory<PoolablePropertyChangeEvent> {

	/** The Constant LOGGER. */
	private static final Log LOGGER = LogFactory.getLog(PropertyChangeEventFactory.class);

	/** The Constant singleton. */
	private static PropertyChangeEventFactory singleton;

	/**
	 * The Class PoolableObjectFactoryImpl.
	 */
	protected static final class PoolableObjectFactoryImpl extends BasePoolableObjectFactory {

		/**
		 * non-Javadoc.
		 * @return the object
		 * @see org.apache.commons.pool.BasePoolableObjectFactory#makeObject()
		 */
		@Override
		public Object makeObject() {
			return new PoolablePropertyChangeEvent();
		}

		/**
		 * non-Javadoc.
		 * @param obj the obj
		 * @throws Exception the exception
		 * @see org.apache.commons.pool.BasePoolableObjectFactory#passivateObject(java.lang.Object)
		 */
		@Override
		public void passivateObject(final Object obj) throws Exception {
			((PoolablePropertyChangeEvent)obj).init();

			super.passivateObject(obj);
		}
	}

	static {
		try {
			singleton = InstantiationHelper.getInstance().newInstance(PropertyChangeEventFactory.class);
		}
		catch (final Exception e) {
			LOGGER.fatal("Can not instantiate the " + PropertyChangeEventFactory.class.getName(), e);

			throw new Error(e);
		}
	}

	/**
	 * returns the singleton.
	 * @return <code>PropertyChangeEventFactory</code>
	 */
	public static PropertyChangeEventFactory getSingleton() {
		return singleton;
	}

	/** The Constant pool. */
	private final transient GenericObjectPool pool;

	/**
	 * The Constructor.
	 */
	protected PropertyChangeEventFactory() {
		super();

		final Config config = new Config();
		final ConfigLoaderHelper helper = ConfigLoaderHelper.getInstance();
		final Properties properties = new Properties();
		final PoolableObjectFactory factory = new PoolableObjectFactoryImpl();

		helper.load(config, properties, factory);
		pool = helper.instantiate(factory, properties, config);
		pool.setConfig(config);
	}

	/*
	 * (non-Javadoc)
	 * @see org.infodavid.common.pool.AbstractPooledFactory#doBorrow()
	 */
	@Override
	protected PoolablePropertyChangeEvent doBorrow() {
		PoolablePropertyChangeEvent obj = null;

		try {
			obj = (PoolablePropertyChangeEvent)getDelegate().borrowObject();
		}
		catch (final Exception e) {
			throw new RuntimeException(e);
		}

		return obj;
	}

	/*
	 * (non-Javadoc)
	 * @see org.infodavid.common.pool.AbstractPooledFactory#doInvalidate(java.io.Serializable )
	 */
	@Override
	protected void doInvalidate(final PoolablePropertyChangeEvent obj) {
		try {
			getDelegate().invalidateObject(obj);
		}
		catch (final Exception e) {
			throw new RuntimeException(e);
		}
	}

	/*
	 * (non-Javadoc)
	 * @see org.infodavid.common.pool.AbstractPooledFactory#doRelease(java.io.Serializable )
	 */
	@Override
	protected void doRelease(final PoolablePropertyChangeEvent obj) {
		try {
			getDelegate().returnObject(obj);
		}
		catch (final Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * Gets the delegate.
	 * @return the delegate
	 */
	public GenericObjectPool getDelegate() {
		return pool;
	}
}
